-- priority_monster
-- create by wangy
-- 优先杀怪流程

-- 非物理攻击
local specialDamage = function(grid)
    -- 优先放主动技
    local slimeSkills = SlimeSkillM.getAllSkills();
    for _, id in pairs(slimeSkills) do
        local pos = grid:getPos();
        --local skillId = SlimeSkillM.query(id, "cast_skill_id");
        local target = SkillM.query(id, "target");
        if target == ATTACKER then
            pos = -1;
        end

        if DungeonActionM.go("use_slime_skill", pos, id) then
            return true;
        end
    end

    -- 获取配置表
    local items = PropertyM.getPropertyByTargetType(PROPERTY_ENEMY);
    -- 试剂需要用其它方式判断
    local reagent = {9001, 9002, 9011, 9021};
    -- 带进迷宫的道具
    local dungeonReagent = ME.user.dbase:query("dungeon_item", {});
    for _, classId in pairs(reagent) do
        -- 从正常伤害道具中剔除
        table.removeItem(items, classId);
        if dungeonReagent[classId] and dungeonReagent[classId] > 0 then
            return DungeonActionM.go("use_property", grid:getPos(), classId);
        end
    end

    local excludeItems = {};
    if DungeonM.getDungeonId() == 1 then
        -- 树屋还没激活，第一关需要把一些东西留下
        if not ME.user.tree_house then
            excludeItems = {7000, 7286, 7287, 7288};
        end
    end

    for _, classId in pairs(items) do
        if table.indexOf(excludeItems, classId) < 0 then
            if ItemM.getAmount(ME.user, classId) > 0 then
                return DungeonActionM.go("use_property", grid:getPos(), classId);
            end
        end
    end

    -- 用伤害魔法
    local tactics = AutoFightM.getTacticsCfg()["damage"];
    for _, classId in pairs(tactics["args"]) do
        local skillId = SpellM.query(classId, "cast_skill_id");
        -- 提前判断魔法值不足的情况，否则会一直提示
        if SpellM.calcSpellCost(classId) > ME.user:getMp() then
            return false;
        end

        if SpellM.canUseSpell(classId, grid:getPos()) and
            not SkillM.immunitySkill(ME.user, grid.monster, skillId) then
            return DungeonActionM.go("use_spell", grid:getPos(), classId);
        end
    end
    return false;
end

-- 简单的Demage
local easyDemage = function(grid)
    local target = grid.monster;
    local prop = PropM.combine(target, "resist", "attack");
    if prop and tonumber(prop[3]) == 1000 then
        -- 100%物抗，不走这里
        return false;
    end

    -- 可以物理攻击得到的怪物
    -- 目测砍一下就会死掉的
    if grid:canHit() and ME.user:getAttack() >= grid.monster:getHp() and
        ME.user:getHp() > grid.monster:getAttack() and
        DungeonActionM.go("physic_attack", grid:getPos()) then
        return true;
    end
    return false;
end

-- 随机给自己一个buff
local buff = function(grid)
    -- 使用buff魔法
    local tactics = AutoFightM.getTacticsCfg()["buff"];

    -- 整理自己有的可以用的卷轴
    local spells = {};
    for _, classId in pairs(tactics["args"]) do
        local skillId = SpellM.query(classId, "cast_skill_id");
        -- 提前判断魔法值不足的情况，否则会一直提示
        if SpellM.calcSpellCost(classId) > ME.user:getMp() then
            return false;
        end

        if ItemM.getAmount(ME.user, classId) > 0 and
            SpellM.canUseSpell(classId, grid:getPos()) and
            not SkillM.immunitySkill(ME.user, grid.monster, skillId) then
            table.insert(spells, classId);
        end
    end

    if #spells <= 0 then
        -- 没有buff卷轴
        return false;
    end

    -- 随机使用卷轴
    local index = math.random(#spells);
    local classId = spells[index];
    return DungeonActionM.go("use_spell", -1, classId);
end

-- 随机给怪物一个debuff
local debuff = function(grid)
    -- 使用debuff魔法
    local tactics = AutoFightM.getTacticsCfg()["debuff"];

    -- 整理自己有的可以用的卷轴
    local spells = {};
    for _, classId in pairs(tactics["args"]) do
        local skillId = SpellM.query(classId, "cast_skill_id");
        -- 提前判断魔法值不足的情况，否则会一直提示
        if SpellM.calcSpellCost(classId) > ME.user:getMp() then
            return false;
        end

        if ItemM.getAmount(ME.user, classId) > 0 and
            SpellM.canUseSpell(classId, grid:getPos()) and
            not SkillM.immunitySkill(ME.user, grid.monster, skillId) then
            table.insert(spells, classId);
        end
    end

    if #spells <= 0 then
        -- 没有debuff卷轴
        return false;
    end

    -- 随机使用一个
    local index = math.random(#spells);
    local classId = spells[index];
    return DungeonActionM.go("use_spell", grid:getPos(), classId);
end

-- 击杀怪物
local fight = function(aliveMonsters, args)
    local pos = -1;
    local baseId = args["base_id"];

    for i = 1, #aliveMonsters do
        local grid = DungeonM.getGridByPos(aliveMonsters[i]);
        local classId = grid.monster:query("base_class_id");
        if baseId and classId and table.indexOf(baseId, classId) >= 0 then
            -- 找到一个相应基类怪物
            pos = aliveMonsters[i];
            break;
        end
    end

    -- 没有找到优先击杀的怪物
    if pos == -1 then
        return false;
    end

    local grid = DungeonM.getGridByPos(pos);

    -- 如果怪物已经死亡了
    if not grid.monster or grid.monster:isDead() then
        return false;
    end

    -- 可以物理攻击得到的怪物
    -- 过分【简单】的怪物，直接使用物理攻击
    local easyPhysics = args["easy_physics"];
    if easyPhysics == 1 then
        if easyDemage(grid) then
            return grid:getPos();
        end
    end

    local buffChance = args["buff_chance"];
    local debuffChance = args["debuff_chance"];
    local physicsChance = args["physics_chance"];

    -- 概率给对方debuff/对方没有debuff的时候才使用
    if #PropM.getDebuff(grid.monster) <= 0 then
        if debuffChance and math.random(debuffChance[2]) <= debuffChance[1] then
            if debuff(grid) then
                return grid:getPos();
            end
        end
    end

    -- 概率给自己加buff
    if #PropM.getBuff(ME.user) <= 0 then
        if buffChance and math.random(buffChance[2]) <= buffChance[1] then
            if buff(grid) then
                return grid:getPos();
            end
        end
    end

    -- 判断是否是需要概率使用魔法/物品/主动技
    local physic = true;
    if physicsChance and
        math.random(physicsChance[2]) > physicsChance[1] then
        physic = false;
    end

    if not physic then
        -- 使用特殊伤害
        if specialDamage(grid) then
            return grid:getPos();
        end
    end

    -- 尝试物理攻击
    if grid:canHit() and DungeonActionM.go("physic_attack", grid:getPos()) then
        return grid:getPos();
    end

    -- 物理打不到的还是用特殊伤害干吧
    if specialDamage(grid) then
        return grid:getPos();
    end
end


return {
    -- 判断
    canTrigger = function(args)
        -- 判断是否有存活的怪物
        local aliveMonsters = AutoFightM.getData()["aliveMonsters"];
        if aliveMonsters and #aliveMonsters > 0 then
            return true;
        end
        return false;
    end,

    -- 触发
    trigger = function(args)
        local aliveMonsters = AutoFightM.getData()["aliveMonsters"];
        if not aliveMonsters or #aliveMonsters <= 0 then
            return false;
        end

        -- 击杀怪物
        local ret = fight(aliveMonsters, args);
        if ret then
            -- 抛出事件
            EventMgr.fire(event.PLAYER_MOVE, ret);
            return true;
        end
        return false;
    end,
};
